home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_351 / pdc / libsrc.lzh / LibSrc / Math / mscanf.c < prev    next >
C/C++ Source or Header  |  1990-04-07  |  12KB  |  451 lines

  1. /*
  2.  * Libraries and headers for PDC release 3.3 (C) 1989 Lionel Hummel.
  3.  * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
  4.  * PDC I/O Library (C) 1987 by J.A. Lydiatt.
  5.  *
  6.  * This code is freely redistributable upon the conditions that this 
  7.  * notice remains intact and that modified versions of this file not
  8.  * be included as part of the PDC Software Distribution without the
  9.  * express consent of the copyright holders.  No warrantee of any
  10.  * kind is provided with this code.  For further information, contact:
  11.  *
  12.  *  PDC Software Distribution    Internet:                     BIX:
  13.  *  P.O. Box 4006             or hummel@cs.uiuc.edu            lhummel
  14.  *  Urbana, IL  61801-8801       petersen@uicsrd.csrd.uiuc.edu
  15.  */
  16.  
  17. /*
  18.     fscanf.c - Routines for formatted Input
  19.  
  20.     sscanf(buf, fmt, args)            Scan from a memory buffer
  21.         char           *buf, *fmt;
  22.         void           *args;
  23.  
  24.     fscanf(fp, fmt, args)            Scan from a file pointer
  25.         FILE           *fp;
  26.         char           *fmt;
  27.         void           *args;
  28.  
  29.     scanf(fmt, args)            Scan from stdin
  30.         char           *fmt;
  31.         void           *args;
  32. */
  33.  
  34. #include <stdio.h>
  35. #include <varargs.h>
  36. #include <ctype.h>
  37.  
  38. #define TRUE    1
  39. #define FALSE   0
  40.  
  41. _scanchar(fp, buffer)
  42.     FILE           *fp;
  43.     char          **buffer;
  44. {
  45.     char           *ptr;
  46.  
  47.     if (fp != NULL)
  48.         return (fgetc(fp));
  49.     else if (*buffer != NULL) {
  50.         ptr = *buffer;
  51.         if (*ptr == '\0')
  52.             return (EOF);
  53.         else {
  54.             *buffer += 1;
  55.             return (*ptr);
  56.         }
  57.     }
  58.     return (EOF);
  59. }
  60.  
  61.  
  62. _unscanc(fp, buffer, ch)
  63.     FILE           *fp;
  64.     char          **buffer, ch;
  65. {
  66.     char           *ptr;
  67.  
  68.     if (fp != NULL)
  69.         ungetc(ch, fp);
  70.     else if (*buffer != NULL) {
  71.         *buffer -= 1;
  72.         **buffer = ch;
  73.     }
  74. }
  75.  
  76.  
  77. _scanstr(fp, buffer, str, maxlen)
  78.     FILE           *fp;
  79.     char          **buffer, *str;
  80.     int             maxlen;
  81. {
  82.     int             i, ch;
  83.  
  84.     do {
  85.         ch = _scanchar(fp, buffer);
  86.         if (ch == EOF)
  87.             return (0);
  88.     } while (isspace(ch));
  89.  
  90.     _unscanc(fp, buffer, ch);
  91.  
  92.     for (i = 0; i < maxlen; i++) {
  93.         ch = _scanchar(fp, buffer);
  94.         if (isspace(ch) || ch == EOF)
  95.             goto done;
  96.         *str++ = ch;
  97.     }
  98. done:
  99.     *str = '\0';
  100.     return (i != 0);
  101. }
  102.  
  103.  
  104.  
  105. _scanint(fp, buffer, result, base, maxlen)
  106.     FILE           *fp;
  107.     char          **buffer;
  108.     int            *result, base, maxlen;
  109. {
  110.     int             digit, value = 0;
  111.     int             negative, ch, i;
  112.  
  113.     *result = value;
  114.  
  115.     do {
  116.         ch = _scanchar(fp, buffer);
  117.         if (ch == EOF)
  118.             return (0);
  119.     } while (isspace(ch));
  120.  
  121.     if (!(negative = (ch == '-')))
  122.         _unscanc(fp, buffer, ch);
  123.  
  124.     for (i = 0; i < maxlen; i++) {
  125.         ch = _scanchar(fp, buffer);
  126.         if (ch == EOF)
  127.             goto done;
  128.         if (base == 16) {
  129.             if (isdigit(ch))
  130.                 value = value * base + ch - '0';
  131.             else if (ch >= 'a' && ch <= 'f')
  132.                 value = value * base + ch - 'a' + 10;
  133.             else if (ch >= 'A' && ch <= 'F')
  134.                 value = value * base + ch - 'A' + 10;
  135.             else if (!(i == 1 && (ch == 'X' || ch == 'x'))) {
  136.                 _unscanc(fp, buffer, ch);
  137.                 goto done;
  138.             }
  139.         }
  140.         else {
  141.             digit = ch - '0';
  142.             if ((digit >= 0) && (digit < base))
  143.                 value = value * base + digit;
  144.             else {
  145.                 _unscanc(fp, buffer, ch);
  146.                 goto done;
  147.             }
  148.         }
  149.     }
  150. done:
  151.     if (negative)
  152.         *result = -value;
  153.     else
  154.         *result = value;
  155.     return (i != 0);
  156. }
  157.  
  158.  
  159. _scandouble(fp, buffer, result, maxlen)
  160.     FILE           *fp;
  161.     char          **buffer;
  162.     int             maxlen;
  163.     double         *result;
  164. {
  165.     double          value = 0.0;
  166.     double          intp, frac;
  167.     int             state;
  168.     int             digit, exp;
  169.     int             negative, ch, i, nexp;
  170.  
  171.     *result = value;
  172.     exp = 0;
  173.  
  174.     do {
  175.         ch = _scanchar(fp, buffer);
  176.         if (ch == EOF)
  177.             return (0);
  178.     } while (isspace(ch));
  179.  
  180.     if (!(negative = (ch == '-')))
  181.         _unscanc(fp, buffer, ch);
  182.  
  183.     for (i = 0; i < maxlen; i++) {
  184.         ch = _scanchar(fp, buffer);
  185.         if (ch == EOF)
  186.             goto done;
  187.         digit = ch - '0';
  188.         if ((digit >= 0) && (digit < 10))
  189.             value = value * 10 + digit;
  190.         else
  191.             break;
  192.     }
  193.     if (ch == '.') {
  194.         frac = 1.0;
  195.         for (; i < maxlen; i++) {
  196.             ch = _scanchar(fp, buffer);
  197.             if (ch == EOF)
  198.                 goto done;
  199.             digit = ch - '0';
  200.             if (digit < 0 || digit > 9)
  201.                 break;
  202.             else {
  203.                 frac /= 10.0;
  204.                 value += frac * digit;
  205.             }
  206.         }
  207.     }
  208.     if (ch == 'E' || ch == 'e') {
  209.         ch = _scanchar(fp, buffer);
  210.         nexp = 0;
  211.         if (ch == '-' || ch == '+')
  212.             nexp = (ch == '-');
  213.         else
  214.             _unscanc(fp, buffer, ch);
  215.         exp = 0;
  216.         for (; i < maxlen; i++) {
  217.             ch = _scanchar(fp, buffer);
  218.             if (ch == EOF)
  219.                 goto done;
  220.             digit = ch - '0';
  221.             if (digit < 0 || digit > 9)
  222.                 break;
  223.             else
  224.                 exp = exp * 10 + digit;
  225.         }
  226.         if (nexp) {
  227.             while (exp > 0) {
  228.                 value /= 10.0;
  229.                 --exp;
  230.             }
  231.         }
  232.         else {
  233.             while (exp > 0) {
  234.                 value *= 10.0;
  235.                 --exp;
  236.             }
  237.         }
  238.     }
  239.     _unscanc(fp, buffer, ch);
  240.  
  241. done:
  242.     if (negative)
  243.         *result = -value;
  244.     else
  245.         *result = value;
  246.     return (i != 0);
  247. }
  248.  
  249.  
  250. _doscan(fmt, args, fp, buffer)
  251.     char           *fmt, *buffer;
  252.     FILE           *fp;
  253.     void           *args;
  254. {
  255.     char            local[128];
  256.     int             ch, maxlen, skip, check;
  257.     int             match = 0;
  258.     char           *aptr = (char *) args;
  259.     char           *fptr = fmt;
  260.     char           *cptr;
  261.     int            *iptr;
  262.     short          *sptr;
  263.     unsigned int   *uptr;
  264.     float          *fdptr;
  265.     double         *dptr, dval;
  266.  
  267.     while (*fptr) {
  268.         check = 0;
  269.         switch (*fptr) {
  270.         case ' ':
  271.         case '\t':
  272.         case '\n':
  273.             check = ' ';
  274.             break;
  275.         case '%':
  276.             fptr++;
  277.             if ((check = (*fptr)) == '%')
  278.                 break;
  279.             check = 0;
  280.             maxlen = 1024;
  281.             if (skip = ((*fptr) == '*'))
  282.                 fptr++;
  283.             if (isdigit(*fptr)) {
  284.                 maxlen = 0;
  285.                 while (isdigit(*fptr)) {
  286.                     maxlen = maxlen * 10 + (*fptr) - '0';
  287.                     fptr++;
  288.                 }
  289.             }
  290.             switch (*fptr) {
  291.             case 'c':
  292.                 ch = _scanchar(fp, &buffer);
  293.                 if (ch == EOF)
  294.                     return (match);
  295.                 if (!skip) {
  296.                     cptr = va_arg(aptr, char *);
  297.                     *cptr = ch;
  298.                     match++;
  299.                 }
  300.                 break;
  301.             case 'd':
  302.             case 'D':
  303.                 if (!_scanint(fp, &buffer, &ch, 10, maxlen))
  304.                     return (match);
  305.                 if (!skip) {
  306.                     iptr = va_arg(aptr, int *);
  307.                     *iptr = ch;
  308.                     match++;
  309.                 }
  310.                 break;
  311.             case 'e':
  312.             case 'f':
  313.             case 'g':
  314.                 if (!_scandouble(fp, &buffer, &dval, maxlen))
  315.                     return (match);
  316.                 if (!skip) {
  317.                     fdptr = va_arg(aptr, float *);
  318.                     *fdptr = dval;
  319.                     match++;
  320.                 }
  321.                 break;
  322.             case 'E':
  323.             case 'F':
  324.             case 'G':
  325.                 if (!_scandouble(fp, &buffer, &dval, maxlen))
  326.                     return (match);
  327.                 if (!skip) {
  328.                     dptr = va_arg(aptr, double *);
  329.                     *dptr = dval;
  330.                     match++;
  331.                 }
  332.                 break;
  333.             case 'h':
  334.                 if (!_scanint(fp, &buffer, &ch, 10, maxlen))
  335.                     return (match);
  336.                 if (!skip) {
  337.                     sptr = va_arg(aptr, short *);
  338.                     *sptr = ch;
  339.                     match++;
  340.                 }
  341.                 break;
  342.             case 'l':
  343.             case 'L':
  344.                 ++fptr;
  345.                 switch (*fptr) {
  346.                 case 'd':
  347.                 case 'D':
  348.                     if (!_scanint(fp, &buffer, &ch, 10, maxlen))
  349.                         return (match);
  350.                     if (!skip) {
  351.                         iptr = va_arg(aptr, int *);
  352.                         *iptr = ch;
  353.                         match++;
  354.                     }
  355.                     break;
  356.                 case 'e':
  357.                 case 'E':
  358.                 case 'f':
  359.                 case 'F':
  360.                 case 'g':
  361.                 case 'G':
  362.                     if (!_scandouble(fp, &buffer, &dval, maxlen))
  363.                         return (match);
  364.                     if (!skip) {
  365.                         dptr = va_arg(aptr, double *);
  366.                         *dptr = dval;
  367.                         match++;
  368.                     }
  369.                     break;
  370.                 }
  371.                 break;
  372.             case 'o':
  373.                 if (!_scanint(fp, &buffer, &ch, 8, maxlen))
  374.                     return (match);
  375.                 if (!skip) {
  376.                     iptr = va_arg(aptr, int *);
  377.                     *iptr = ch;
  378.                     match++;
  379.                 }
  380.                 break;
  381.             case 's':
  382.                 if (skip) {
  383.                     if (!_scanstr(fp, &buffer, local, maxlen))
  384.                         return (match);
  385.                 }
  386.                 else {
  387.                     cptr = va_arg(aptr, char *);
  388.                     if (!_scanstr(fp, &buffer, cptr, maxlen))
  389.                         return (match);
  390.                     match++;
  391.                 }
  392.                 break;
  393.             case 'u':
  394.                 if (!_scanint(fp, &buffer, &ch, 10, maxlen))
  395.                     return (match);
  396.                 if (!skip) {
  397.                     uptr = va_arg(aptr, unsigned *);
  398.                     *uptr = ch;
  399.                     match++;
  400.                 }
  401.                 break;
  402.             case 'x':
  403.                 if (!_scanint(fp, &buffer, &ch, 16, maxlen))
  404.                     return (match);
  405.                 if (!skip) {
  406.                     iptr = va_arg(aptr, int *);
  407.                     *iptr = ch;
  408.                     match++;
  409.                 }
  410.                 break;
  411.             default:
  412.                 break;
  413.             }
  414.             break;
  415.         default:
  416.             break;
  417.         }
  418.         fptr++;
  419.         if (check > 0 && !isspace(check)) {
  420.             ch = _scanchar(fp, &buffer);
  421.             if (ch != check)
  422.                 return (match);
  423.         }
  424.     }
  425.     return (match);
  426. }
  427.  
  428. sscanf(buf, fmt, args)
  429.     char           *buf, *fmt;
  430.     void           *args;
  431. {
  432.     FILE            fp;
  433.  
  434.     return (_doscan(fmt, &args, NULL, buf));
  435. }
  436.  
  437. fscanf(fp, fmt, args)
  438.     FILE           *fp;
  439.     char           *fmt;
  440.     void           *args;
  441. {
  442.     return (_doscan(fmt, &args, fp, NULL));
  443. }
  444.  
  445. scanf(fmt, args)
  446.     char           *fmt;
  447.     void           *args;
  448. {
  449.     return (_doscan(fmt, &args, stdin, NULL));
  450. }
  451.